﻿
/*******************************************************************************************
// ©2009 Microsoft Corporation.  This code is provided under the Microsoft Public License.
*******************************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Rtc.Collaboration.AudioVideo;
using Microsoft.Rtc.Collaboration;
using System.Configuration;
using BackToBack;

namespace ClientBilling
{
    public class IncomingCallRouter
    {
        #region Instance Variables
        ApplicationEndpoint _appEndpoint;
        AudioVideoCall _call;
        ConversationParticipant _remoteParticipant;
        #endregion

        public IncomingCallRouter(ApplicationEndpoint appEndpoint)
        {
            _appEndpoint = appEndpoint;
        }

        /// <summary>
        /// This method is called whenever an AudioVideoCall comes in to the endpoint.
        /// </summary>
        public void RouteIncomingClientCall(object sender, CallReceivedEventArgs<AudioVideoCall> args)
        {
            _call = args.Call;
            _remoteParticipant = args.RemoteParticipant;

            // Determine who is calling and get the first case associated with that client.
            Case callerMainCase = GetCaseForCaller();

            if (callerMainCase == null)
            {
                // If the caller is not a known client, reject the call.
                _call.EndTerminate(_call.BeginTerminate(null, null));
            }
            else
            {
                // Create a new AudioVideoCall to place a call to the lawyer.
                Conversation lawyerConv = new Conversation(_appEndpoint);
                AudioVideoCall avCall = new AudioVideoCall(lawyerConv);

                // Use a BackToBack agent to bridge the incoming client call with a separate call to the lawyer.
                BackToBackUserAgent backToBackAgent = new BackToBackUserAgent(avCall, _call);

                // Begin tracking the call duration for billing purposes.
                BilledCallTracker.AttachCaseToConversation(callerMainCase, avCall.Conversation);

                // Initiate the back-to-back call.
                backToBackAgent.BeginParticipate(ConfigUtility.LawyerSipUri, IncomingClientCallAccepted, avCall);
            }
        }

        #region Call Transferring

        /// <summary>
        /// Send the extended window message to the lawyer's call after the calls are bridged.
        /// </summary>
        private void IncomingClientCallAccepted(IAsyncResult result)
        {
            Call lawyerCall = (Call)result.AsyncState;

            // Send the INFO message to the lawyer's call.
            ExtendedWindowMessage.SendToCall(lawyerCall);
        }

        /// <summary>
        /// Transfer the call to the lawyer synchronously, using the lawyer's SIP URI.
        /// </summary>
        private void TransferCallToLawyer()
        {
            _call.EndTransfer(_call.BeginTransfer(ConfigUtility.LawyerSipUri,
                new CallTransferOptions(CallTransferType.Attended), null, null));
        }

        #endregion

        #region Call Billing

        /// <summary>
        /// Figure out which client is calling, and get the first case associated with that client.
        /// </summary>
        private Case GetCaseForCaller()
        {
            Client callClient = CrmSystem.GetClients().Find(client => client.SipUri == _remoteParticipant.Uri);

            // If no client matches the caller, return null for the case.
            if (callClient == null)
            {
                return null;
            }

            Case callCase = callClient.PrimaryCase;
            return callCase;
        }

        #endregion
    }
}
